//
// Created by yanhai on 2021/11/5.
//

#include "spare_queue_proxy.h"


bool SpareQueueProxy::Prealloc()
{
    assert(Len() == 0); // 初始化后只调用一次

    for (length_type i = 0; i < prealloc; i++) {
        value_type *node = NewNode();
        if (node == nullptr)
            return false;

        spareQueue->Enqueue(node);
    }

    return true;
}

void SpareQueueProxy::Clear()
{
    value_type *node;
    while ((node = spareQueue->Dequeue()) != nullptr) {
        FreeNode(node);
    }
}

#include <iostream>
/** \brief Make sure we have enough spare flows.
 *
 *  Enforce the prealloc parameter, so keep at least prealloc flows in the
 *  spare queue and free flows going over the limit.
 *
 *  \retval true if the queue was properly updated (or if it already was in good shape)
 *  \retval false otherwise.
 */
bool SpareQueueProxy::Update()
{
    length_type toalloc = 0, tofree = 0, len;

    len = spareQueue->Len();

    if (len < prealloc * 0.2) {
        toalloc = prealloc * 0.4 - len;

        std::cout << "update: alloc " << toalloc << std::endl;
        for (length_type i = 0; i < toalloc; i++) {
            value_type *node = NewNode();
            if (node == nullptr)
                return false;

            spareQueue->Enqueue(node);
        }
    } else if (len > prealloc) {
        tofree = len - prealloc;

        std::cout << "update: free " << tofree << std::endl;
        for (length_type i = 0; i < tofree; i++) {
            /* FlowDequeue locks the queue */
            value_type *node = spareQueue->Dequeue();
            if (node == nullptr)
                return true;

            FreeNode(node);
        }
    }

    return true;
}
